/* ======================================================================================== *\

		FILE:				Utils.h
		AUTHOR:				Jack Hoxley

		DESCRIPTION:		Provides definitions for various utility functions used
							elsewhere in the program

		CHANGE:				5th May 2007
								Simple logging messages interface defined.
							8th May 2007
								Declarations for IntegerVector and CoordinateList
								Simple RandomNum definition
								Implemented IsInRange() helper method
							12th May 2007
								Removed RandomNum
								Added RndInRange()
							28th July 2007
								Added operator[] overload for IntegerVector

\* ======================================================================================== */

#ifndef INC_UTILS_H
#define INC_UTILS_H

// System headers
// --------------
#pragma warning( disable : 4995 ) // Not interested in deprectation warnings
#include <vector>
#pragma warning( default : 4995 )


// Define necessary macros
// -----------------------
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)

#ifdef ALLOW_DEBUG_MESSAGES
	#define WARN_OUT( msg ) Utils::OutputMessage( Utils::Warning, WIDEN( __FUNCTION__ ), __LINE__, (msg) )
	#define ERR_OUT( msg )  Utils::OutputMessage( Utils::Error, WIDEN( __FUNCTION__ ), __LINE__, (msg) )
	#define INFO_OUT( msg ) Utils::OutputMessage( Utils::Information, WIDEN( __FUNCTION__ ), __LINE__, (msg) )
#else
	// Define simple stubs for builds that don't want
	// to generate any outputs
	#define WARN_OUT( msg )
	#define ERR_OUT( msg )
	#define INFO_OUT( msg )
#endif

namespace Utils
{
	enum MessageClass
	{
		Warning,
		Error,
		Information
	};

	void OutputMessage( MessageClass MsgClass, WCHAR* wcFunction, int iLine, const WCHAR *wcMessage );

	// Integer coordinates are used for
	// the pipe simulation
	struct IntegerVector
	{
		static const UINT32 X_AXIS = 0;
		static const UINT32 Y_AXIS = 1;
		static const UINT32 Z_AXIS = 2;

		int x;
		int y;
		int z;

		IntegerVector( )
		{
			x = y = z = 0;
		}

		IntegerVector( const int& _x, const int& _y, const int& _z )
		{
			x = _x;
			y = _y;
			z = _z;
		}

		inline
		int operator[](unsigned axis) const
		{
			if( X_AXIS == axis ) return x;
			if( Y_AXIS == axis ) return y;
			if( Z_AXIS == axis ) return z;

			// silent error
			return 0;
		}
	};

	typedef std::vector< IntegerVector > CoordinateList;

	// Simple utility method:
	template<typename T>
	bool IsInRange( const T& val, const T& lower_bound, const T& upper_bound )
	{
		return (val >= lower_bound) && (val <= upper_bound );
	}

	int RndInRange( const int& lower, const int& upper );
}

#endif